home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / DB_CLIPP / 2614.ZIP / DISPLA.ZIP / DISPLAY.C < prev    next >
Text File  |  1990-12-22  |  20KB  |  712 lines

  1. /* display.c */
  2.  
  3. // this #define chooses whether or not Clipper 5.0 code is to be generated
  4.  
  5. #define CLIPPER5
  6.  
  7.  
  8. #include "extend.h"
  9.  
  10. #include "display.h"
  11. #include "keys.h"
  12.  
  13.  
  14.  
  15. /*
  16.  * d_chattr() replace the color attribute with a new one starting at
  17.  * location x, y and going for length len.
  18.  *
  19.  */
  20.  
  21.  
  22. void d_chattr(int x, int y, int len, int attr)
  23. {
  24.     int i;
  25.     char far *vmem;
  26.  
  27.     vmem = d_vseg;
  28.     FP_OFF(vmem) = (y * 160) + (x * 2) + 1;     // calc the screen memory coord
  29.  
  30.     for (i = 0; i < len; i++, vmem += 2)        // write the new attribute value
  31.         *vmem = (char) attr;
  32. }
  33.  
  34.  
  35.  
  36.  
  37. /*
  38.  *  d_keyin() gets the next key typed and does any translation needed.
  39.  *  Some keys are converted to a common name - like the up arrow is
  40.  *  converted to the UP value which also is the Ctrl-E value.  This
  41.  *  allows the Wordstar-like control keys to be used.  Only extended
  42.  *  keys are translated - the values of the defines were chosen to
  43.  *  match up with the non-extended key codes.
  44.  *
  45.  */
  46.  
  47. unsigned char d_keyin()
  48. {
  49.     unsigned char ch;
  50.  
  51.     ch = (unsigned char) d_getkey();        // get the next key
  52.     if ( ch == 0x00 )                       // check to see if it's extended
  53.     {
  54.         ch = (unsigned char) d_getkey();    // if so, read the second part
  55.         switch ( ch )                       //  and convert it
  56.         {
  57.             case 75   : ch = LFT;    break;
  58.             case 77   : ch = RGT;    break;
  59.             case 72   : ch = UP;     break;
  60.             case 80   : ch = DN;     break;
  61.             case 71   : ch = HOME;   break;
  62.             case 79   : ch = ENND;   break;
  63.             case 73   : ch = PGUP;   break;
  64.             case 81   : ch = PGDN;   break;
  65.             case 62   : ch = F4;     break;
  66.             case 117  : ch = CENND;  break;
  67.             case 119  : ch = CHOME;  break;
  68.             case 118  : ch = CPGDN;  break;
  69.             case 132  : ch = CPGUP;  break;
  70.             case 116  : ch = CRGT;   break;
  71.             case 115  : ch = CLFT;   break;
  72.             case 82   : ch = INS;    break;
  73.             case 83   : ch = DEL;    break;
  74.             case 68   : ch = F0;     break;
  75.             case 59   : ch = F1;     break;
  76.             case 60   : ch = F2;     break;
  77.             case 61   : ch = F3;     break;
  78.             case 63   : ch = F5;     break;
  79.             case 64   : ch = F6;     break;
  80.             case 65   : ch = F7;     break;
  81.             case 66   : ch = F8;     break;
  82.             case 67   : ch = F9;     break;
  83.             case 113  : ch = AF0;    break;
  84.             case 104  : ch = AF1;    break;
  85.             case 105  : ch = AF2;    break;
  86.             case 106  : ch = AF3;    break;
  87.             case 107  : ch = AF4;    break;
  88.             case 108  : ch = AF5;    break;
  89.             case 109  : ch = AF6;    break;
  90.             case 110  : ch = AF7;    break;
  91.             case 111  : ch = AF8;    break;
  92.             case 112  : ch = AF9;    break;
  93.             case 94   : ch = CF1;    break;
  94.             case 95   : ch = CF2;    break;
  95.             case 96   : ch = CF3;    break;
  96.             case 97   : ch = CF4;    break;
  97.             case 98   : ch = CF5;    break;
  98.             case 99   : ch = CF6;    break;
  99.             case 100  : ch = CF7;    break;
  100.             case 101  : ch = CF8;    break;
  101.             case 102  : ch = CF9;    break;
  102.             case 103  : ch = CF0;    break;
  103.             case 120  : ch = ALT1;   break;
  104.             case 121  : ch = ALT2;   break;
  105.             case 122  : ch = ALT3;   break;
  106.             case 123  : ch = ALT4;   break;
  107.             case 124  : ch = ALT5;   break;
  108.             case 125  : ch = ALT6;   break;
  109.             case 126  : ch = ALT7;   break;
  110.             case 127  : ch = ALT8;   break;
  111.             case 128  : ch = ALT9;   break;
  112.             case 129  : ch = ALT0;   break;
  113.             case 130  : ch = ADASH;  break;
  114.             case 131  : ch = AEQL;   break;
  115.             case 30   : ch = ALTA;   break;
  116.             case 48   : ch = ALTB;   break;
  117.             case 46   : ch = ALTC;   break;
  118.             case 32   : ch = ALTD;   break;
  119.             case 18   : ch = ALTE;   break;
  120.             case 33   : ch = ALTF;   break;
  121.             case 34   : ch = ALTG;   break;
  122.             case 35   : ch = ALTH;   break;
  123.             case 23   : ch = ALTI;   break;
  124.             case 36   : ch = ALTJ;   break;
  125.             case 37   : ch = ALTK;   break;
  126.             case 38   : ch = ALTL;   break;
  127.             case 50   : ch = ALTM;   break;
  128.             case 49   : ch = ALTN;   break;
  129.             case 24   : ch = ALTO;   break;
  130.             case 25   : ch = ALTP;   break;
  131.             case 16   : ch = ALTQ;   break;
  132.             case 19   : ch = ALTR;   break;
  133.             case 31   : ch = ALTS;   break;
  134.             case 20   : ch = ALTT;   break;
  135.             case 22   : ch = ALTU;   break;
  136.             case 47   : ch = ALTV;   break;
  137.             case 17   : ch = ALTW;   break;
  138.             case 45   : ch = ALTX;   break;
  139.             case 21   : ch = ALTY;   break;
  140.             case 44   : ch = ALTZ;   break;
  141.             default   : ch = 0;      break;
  142.         }
  143.     }
  144.  
  145.     return ( ch );
  146. }
  147.  
  148.  
  149.  
  150. /*
  151.  * function d_getblock() reads the text file and returns the a block.
  152.  *  the variables offset and buffsize tell it where to start reading and
  153.  *  how many bytes to try to read.  if the block read in would not fill
  154.  *  the buffer then the offset is adjusted so that the start or end of
  155.  *  of the file is positioned at the head or tail of the buffer.
  156.  *
  157.  * it returns the offset into the file of the first byte of the buffer.
  158.  *
  159.  */
  160.  
  161. long d_getblock(long offset)
  162. {
  163.  
  164.         // set the file pointer to the proper offset
  165.         //  and if an error occured then check to see
  166.         //  if a positive offset was requested, if so
  167.         //  then set the pointer to the offset from
  168.         //  the end of the file, otherwise set it from
  169.         //  the beginning of the file.
  170.  
  171.     d_fileseek(d_infile, offset, SEEK_SET);
  172.  
  173.         // read in the file and set the buffer bottom variable equal
  174.         //  to the number of bytes actually read in.
  175.  
  176.     d_buffbot = d_fileread(d_infile, d_buffer, d_buffsize);
  177.  
  178.         // if a full buffer's worth was not read in, make it full.
  179.  
  180.     if (( d_buffbot != d_buffsize ) && ( d_fsize > d_buffsize ))
  181.     {
  182.         if ( offset > 0 )
  183.             d_fileseek(d_infile, (long) -d_buffsize, SEEK_END);
  184.         else
  185.             d_fileseek(d_infile, (long) d_buffsize, SEEK_SET);
  186.  
  187.         d_buffbot = d_fileread(d_infile, d_buffer, d_buffsize);
  188.     }
  189.  
  190.         // return the actual file position */
  191.  
  192.     return(d_filepos(d_infile) - d_buffbot);
  193. }
  194.  
  195. /*
  196.  * d_buff_align makes sure the buffer top and bottom variables point
  197.  * to actual complete lines of text.
  198.  *
  199.  */
  200.  
  201. void d_buff_align()
  202. {
  203.     int i;
  204.  
  205.     d_bufftop = 0;
  206.     d_buffbot = d_buffsize;
  207.  
  208.     if ( d_buffoffset != 0L )   // if the d_buffoffset is otherthan 0
  209.     {
  210.         i = d_bufftop;          // start at the top of the file and scan
  211.                                 // forward until a CR is reached.
  212.  
  213.         while (( d_buffer[i] != CR ) && ( i < d_buffbot ))
  214.             i++;
  215.  
  216.         d_bufftop = i + 2;      // skip past the CR/LF to the first char
  217.     }
  218.  
  219.         // if the buffer offset is not a complete */
  220.         // buffer's length away from the file end */
  221.  
  222.     if ( d_buffoffset + ((long) d_buffbot) != d_fsize )
  223.     {
  224.             // if the file position of the last byte
  225.             //  of the buffer would end up past the
  226.             //  end of the file, then the buffer does
  227.             //  contain a complete buffer full and the
  228.             //  buffer end pointer needs to be set to
  229.             //  the last character of the file.
  230.  
  231.         if ( d_buffoffset + ((long) d_buffbot) > d_fsize )
  232.             d_buffbot = (int) (d_fsize - d_buffoffset);
  233.  
  234.         i = d_buffbot;          // point the end of the buffer to a valid
  235.                                 // complete text line.
  236.  
  237.         while (( d_buffer[i] != CR ) && ( i > d_bufftop ))
  238.             i--;
  239.  
  240.         d_buffbot = i + 2;         // skip past the CR/LF to the first char   */
  241.     }
  242. }
  243.  
  244.  
  245. /*
  246.  * d_win_align takes the value for d_wintop and then figures out where
  247.  * d_winbot would be.  if d_winbot would extend past the end of the
  248.  * buffer, then the top of the window is adjusted to ensure that a full
  249.  * screen of text will appear.  This simplifies the cursor routines.
  250.  *
  251.  */
  252.  
  253.  
  254. void d_win_align()
  255. {
  256.     int i;
  257.  
  258.     d_winbot = d_wintop;    // find out if there is enough text for
  259.     i        = 0;           // full window.
  260.  
  261.     while (( d_winbot < d_buffbot ) && ( i < d_height ))
  262.     {
  263.         if ( d_buffer[d_winbot] == CR )
  264.             i++;
  265.         d_winbot++;
  266.     }
  267.  
  268.     if ( i < d_height )           // if there is not a full window,
  269.     {
  270.         while ( d_buffer[d_winbot] != LF )  // then retrofit d_winbot
  271.             d_winbot--;                     // to the end of a line
  272.  
  273.         d_wintop = d_winbot;
  274.         i        = 0;                       // and setup d_wintop
  275.  
  276.         while (( d_wintop > d_bufftop ) && ( i <= d_height ))
  277.         {
  278.             if ( d_buffer[d_wintop] == LF )
  279.                 i++;
  280.             d_wintop--;
  281.         }
  282.  
  283.         if ( d_wintop != d_bufftop )
  284.             d_wintop += 2;
  285.     }
  286. }
  287.  
  288.  
  289. /*
  290.  * this routine displays the actual text in the window.  This is done
  291.  * by taking each line and placing it in a string.  the screen line
  292.  * is then taken from the appropriate group of characters in the string.
  293.  * this allows a window to page left-right across the buffer without
  294.  * having to use any complex algorithm to calc the needed chars.
  295.  *
  296.  */
  297.  
  298. void d_disp_update(int offset)
  299. {
  300.     int line, col, pos, i;
  301.     char far *vmem;
  302.  
  303.     vmem = d_vseg;
  304.  
  305.     d_refresh = NO;
  306.     line      = 0;
  307.  
  308.     while ( line < d_height )
  309.     {
  310.             // calculate the initial position, this save execution
  311.             // time because each column is considered as a offset
  312.             // from the line start
  313.  
  314.         pos = ((d_sline + line) * 160) + (d_scol * 2);
  315.  
  316.             // copy string to temp buffer
  317.  
  318.         for (i = 0; d_buffer[offset] != CR && offset <= d_winbot; offset++)
  319.         {
  320.             if ( i < d_maxlin )
  321.                 d_lbuff[i++] = d_buffer[offset];
  322.         }
  323.  
  324.         for (; i < d_maxlin; i++)       // fill out with spaces
  325.             d_lbuff[i] = ' ';
  326.  
  327.             // place the proper characters onto the screen
  328.  
  329.         for (i = d_wincol - 1, col = 0; col < d_wincol + d_width - 1; col++)
  330.         {
  331.             FP_OFF(vmem) = pos + (col * 2);
  332.  
  333.             *vmem = d_lbuff[i++];
  334.         }
  335.  
  336.         line   += 1;
  337.         offset += 2;
  338.     }
  339. }
  340.  
  341.  
  342. void d_winup()
  343. {
  344.     int k;
  345.     long i, j;
  346.  
  347.     d_refresh = YES;
  348.     k         = d_wintop - 3;
  349.  
  350.     while (( d_buffer[k] != CR ) && ( k > d_bufftop ))
  351.         k--;
  352.  
  353.     if ( k >= d_bufftop )
  354.     {
  355.         if ( d_buffer[k] == CR )
  356.             k += 2;
  357.  
  358.         d_wintop = k;
  359.         k        = d_winbot - 3;
  360.  
  361.         while ( d_buffer[k] != CR )
  362.             k--;
  363.  
  364.         d_winbot = k + 2;
  365.     }
  366.     else
  367.         if ( ((long) d_bufftop) + d_buffoffset > 0 && d_fsize > d_buffsize )
  368.         {
  369.             i = d_buffoffset + d_wintop;
  370.             j = d_buffoffset - ((long) (d_buffsize / 2));
  371.  
  372.             if ( j < 0 )
  373.                 j = 0;
  374.  
  375.             d_buffoffset = d_getblock(j);
  376.             d_wintop     = ((int) (i - d_buffoffset));
  377.  
  378.             d_buff_align();
  379.             d_win_align();
  380.         }
  381. }
  382.  
  383.  
  384.  
  385. void d_windown()
  386. {
  387.     int k;
  388.     long i, j;
  389.  
  390.     d_refresh = YES;
  391.     k         = d_winbot;
  392.  
  393.     while (( d_buffer[k] != CR ) && ( k <= d_buffbot ))
  394.         k++;
  395.  
  396.     k += 2;
  397.  
  398.     if ( k <= d_buffbot )
  399.     {
  400.         d_winbot = k;
  401.         k        = d_wintop;
  402.  
  403.         while ( d_buffer[k] != CR )
  404.             k++;
  405.  
  406.         d_wintop = k + 2;
  407.     }
  408.     else
  409.         if ( (((long) d_buffbot) + d_buffoffset) < d_fsize && d_fsize > d_buffsize)
  410.         {
  411.             i = d_buffoffset + d_wintop;
  412.             j = i;
  413.  
  414.             if ( j > d_fsize )
  415.                 j = d_fsize - ((long) d_buffsize);
  416.  
  417.             d_buffoffset = d_getblock(j);
  418.  
  419.             if ( i < d_buffoffset )
  420.                 d_wintop = 0;
  421.             else
  422.                 d_wintop = ((int) (i - d_buffoffset));
  423.  
  424.             d_buff_align();
  425.             d_win_align();
  426.         }
  427. }
  428.  
  429.  
  430. /* move the cursor one line down */
  431.  
  432. void d_linedown()
  433. {
  434.     if ( d_winrow < d_eline )   // if cursor not at last line
  435.         d_winrow += 1;
  436.     else                        // otherwise adjust the window top variable
  437.         d_windown();
  438. }
  439.  
  440.  
  441. /* move the cursor one line up */
  442.  
  443. void d_lineup()
  444. {
  445.     if ( d_winrow > d_sline )
  446.         d_winrow -= 1;
  447.     else
  448.         d_winup();
  449. }
  450.  
  451.  
  452. /* go to the top of the file */
  453.  
  454. void d_filetop()
  455. {
  456.     if ( d_buffoffset != 0 )
  457.     {
  458.         d_buffoffset = d_getblock(0L);
  459.  
  460.         d_buff_align();
  461.     }
  462.  
  463.     d_refresh = YES;
  464.     d_wintop  = (int) d_buffoffset;
  465.     d_winrow  = d_sline;
  466.     d_wincol  = 1;
  467.  
  468.     d_win_align();
  469. }
  470.  
  471.  
  472. /* goto the bottom of the file */
  473.  
  474. void d_filebot()
  475. {
  476.     if ( (((long) d_buffbot) + d_buffoffset) < d_fsize && d_fsize > d_buffsize )
  477.     {
  478.         d_buffoffset = d_getblock(d_fsize + 1);
  479.  
  480.         d_buff_align();
  481.     }
  482.  
  483.     d_refresh = YES;
  484.     d_wintop  = d_buffbot - 3;
  485.     d_winrow  = d_eline;
  486.     d_wincol  = 1;
  487.  
  488.     d_win_align();
  489. }
  490.  
  491.  
  492. CLIPPER dispfile()
  493. {
  494.     int i, j, done, hlight, norm;
  495.     int mcount;
  496.     int colinc, brows;
  497.     char rval[2], fname[15];
  498.     char mstr[25];
  499.     unsigned char ch;
  500.  
  501.     FP_SEG(d_vseg) = d_vconfig();       // get the video buffer segment address
  502.  
  503.     strcpy(fname, _parc(1));    // retrieve the filename
  504.  
  505.     if ( _parinfo(12) == 0 )
  506.         d_maxlin = MAXLINE;
  507.     else
  508.         d_maxlin = _parni(12);
  509.  
  510.     d_infile = d_fileopen(fname, READONLY);   // open the file as read-only
  511.  
  512. #ifdef CLIPPER5
  513.     if ( _parinfo(13) == 0 )        // buffer size passed?
  514.         d_buffsize = _parni(13);
  515.     else
  516.         d_buffsize = BUFFERSIZE;
  517.  
  518.     d_buffer = _xalloc(d_buffsize);
  519.     d_lbuff  = _xalloc(d_maxlin);
  520.  
  521.     if (( d_buffer == NULL ) || ( d_lbuff == NULL ))
  522.     {
  523.         d_fileclose(d_infile);
  524.  
  525.         d_infile = 0;
  526.     }
  527. #else
  528.     d_buffsize = BUFFERSIZE;
  529.  
  530.     if ( d_maxlin > MAXLINE )   // prevent rmargin larger than line buff size
  531.         d_maxlin = MAXLINE;
  532. #endif
  533.  
  534.     if ( d_infile == 0 )                      // check for file open error
  535.     {
  536.         rval[0] = (char) 0;     // build the return string char 0 tells
  537.         rval[1] = '\0';         // the calling routine that an error occured
  538.     }
  539.     else                        // if file opened okay, then get parameters
  540.     {
  541.         d_sline = _parni(2);
  542.         d_scol  = _parni(3);
  543.         d_eline = _parni(4);
  544.         d_ecol  = _parni(5);
  545.         j       = _parni(6);
  546.         norm    = _parni(7);
  547.         hlight  = _parni(8);
  548.  
  549.         strcpy(mstr, _parc(9));
  550.  
  551.         brows = _parl(10);
  552.  
  553.         if ( _parinfo(11) == 0 )
  554.             colinc = 1;
  555.         else
  556.             colinc = _parni(11);
  557.  
  558.         d_width      = d_ecol - d_scol + 1;
  559.         d_height     = d_eline - d_sline + 1;
  560.         mcount       = strlen(mstr);
  561.         d_bufftop    = 0;
  562.         d_buffbot    = d_buffsize;
  563.         d_buffoffset = 0;
  564.         d_winrow     = d_sline;
  565.         d_wincol     = 1;
  566.         d_wintop     = 0;
  567.         d_winbot     = 0;
  568.         d_fsize      = d_fileseek(d_infile, 0L, SEEK_END) - 1;
  569.  
  570.             // get the first block
  571.  
  572.         d_fileseek(d_infile, 0L, SEEK_SET);
  573.  
  574.             // if block less than d_buffsize
  575.  
  576.         if ( d_fsize < ((long) d_buffbot) )
  577.             d_buffbot = (int) d_fsize;      // then set buffer bottom
  578.  
  579.         d_buffoffset = d_getblock((long) d_bufftop);
  580.  
  581.         d_buff_align();
  582.         d_win_align();
  583.  
  584.             // point line pointer to line passed by caller
  585.  
  586.         for (i = 1; i < j; i++)
  587.             d_linedown();
  588.  
  589.         done      = NO;
  590.         d_refresh = YES;
  591.  
  592.         for (i = d_sline; i <= d_eline; i++)
  593.             d_chattr(d_scol, i, d_width, norm);
  594.  
  595.         do
  596.         {
  597.             if ( d_refresh == YES )
  598.                 d_disp_update(d_wintop);
  599.  
  600.             if ( brows == NO )
  601.                 d_chattr(d_scol, d_winrow, d_width, hlight);
  602.  
  603.             d_gotoxy(d_scol, d_winrow);
  604.  
  605.             ch = d_keyin();
  606.  
  607.             if ( brows == NO )
  608.                 d_chattr(d_scol, d_winrow, d_width, norm);
  609.  
  610.             switch (ch)
  611.             {
  612.                  case DN    : if ( brows == YES )
  613.                                   d_winrow = d_eline;
  614.  
  615.                               d_linedown();
  616.                               break;
  617.  
  618.                  case UP    : if ( brows == YES )
  619.                                   d_winrow = d_sline;
  620.  
  621.                               d_lineup();
  622.                               break;
  623.  
  624.                  case LFT   : d_wincol -= colinc;
  625.                               d_refresh = YES;
  626.  
  627.                               if ( d_wincol < 1 )
  628.                                   d_wincol = 1;
  629.  
  630.                               break;
  631.  
  632.                  case RGT   : d_wincol += colinc;
  633.                               d_refresh = YES;
  634.  
  635.                               if ( d_wincol > (d_maxlin - d_width) )
  636.                                   d_wincol = d_maxlin - d_width;
  637.  
  638.                               break;
  639.  
  640.                  case HOME  : d_wincol  = 1;
  641.                               d_refresh = YES;
  642.                               break;
  643.  
  644.                  case ENND  : d_wincol  = d_maxlin - d_width;
  645.                               d_refresh = YES;
  646.                               break;
  647.  
  648.                  case CLFT  : d_wincol -= 16;
  649.                               d_refresh = YES;
  650.  
  651.                               if ( d_wincol < 1 )
  652.                                   d_wincol = 1;
  653.  
  654.                               break;
  655.  
  656.                  case CRGT  : d_wincol += 16;
  657.                               d_refresh = YES;
  658.  
  659.                               if ( d_wincol > (d_maxlin - d_width) )
  660.                                   d_wincol = d_maxlin - d_width;
  661.  
  662.                               break;
  663.  
  664.                  case PGUP  : for (i = 0; i < d_height; i++)
  665.                                   d_winup();
  666.  
  667.                               break;
  668.  
  669.                  case PGDN  : for (i = 0; i < d_height; i++)
  670.                                   d_windown();
  671.  
  672.                               break;
  673.  
  674.                  case CPGUP : d_filetop();
  675.                               break;
  676.  
  677.                  case CPGDN : d_filebot();
  678.                               break;
  679.  
  680.                  case RET   : done = YES;
  681.                               break;
  682.  
  683.                  case ESC   : done = YES;
  684.                               break;
  685.  
  686.                  default    : for (i = 0; i <= mcount; i++)
  687.                                   if ( mstr[i] == (char) ch )
  688.                                       done = YES;
  689.                               break;
  690.             }
  691.         } while ( done == NO );
  692.  
  693.             // close the file
  694.  
  695.         d_fileclose(d_infile);
  696.  
  697.         rval[0] = (char) ch;
  698.         rval[1] = '\0';
  699.     }
  700.  
  701.  
  702. #ifdef CLIPPER5
  703.     _xfree(d_buffer);
  704.     _xfree(d_lbuff);
  705. #endif
  706.  
  707.  
  708.         // return key value to Clipper
  709.  
  710.     _retc(rval);
  711. }
  712.